import java.io.*;
import java.net.*;
import java.util.Vector;

public class Server implements Runnable {
	/* For OO */
	private Socket linkTosocket;
	private int ID;
	private BufferedReader in;
	private PrintWriter out;
	private String from_name; // name of host connecting
	
	/* Static stuff */
	private static String header = "<Gruppo20>: ";
	private static int counter = 1;
	private static Vector users;
	
	public static void main (String argv[]) {
		ServerSocket s = null;
		Socket socket = null;
		users = new Vector();
		
		
		try {
			s = new ServerSocket(20122);
			System.out.println("[+] Socket created\n");
			while( (socket = s.accept()) != null){
				 // accetta le conn in entrata; rimane bloccato finche' nn arriva una connessione
				System.out.println("[+] New incoming connection (n. "+(counter)+") from IP "+socket.getInetAddress()+":"+socket.getPort()+"\n");
				
				Server user;
				Thread current = new Thread(user = new Server(socket));
				current.setDaemon(true);
				users.addElement(user); // save user into vector
				current.start(); // start the user's thread
			}
			//s.close();
		}
		catch(BindException e){ System.out.println("ERRORE: Porta gia' in uso"); }
		catch(IOException e) { System.out.println(e); }
	}
	
	public Server(Socket socket) {
		linkTosocket = socket;
		ID = counter++; 
		InetAddress source = linkTosocket.getInetAddress();
		from_name = source.getHostName();
	}

	public void run() {
		try{
			in = new BufferedReader( new InputStreamReader( linkTosocket.getInputStream() ) ); // lettura di dati che vengono dal client
			
			out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(linkTosocket.getOutputStream() ) ) , true);
			String msg = null;
			
			do
			{
				if(msg == null) msg = in.readLine();
				System.out.println("New msg from "+from_name+": "+msg);
				try {
				if (msg.startsWith(".w")) { // build up list of host names
					int k;
					StringBuffer fred = new StringBuffer("WHO HERE?\n");
					for (k=0;k<users.size();k++) {
					Server user = (Server) users.elementAt(k);
					fred.append(user.from_name);
					fred.append(" ");
					}
					msg = fred.toString();
				}
				if(msg.equalsIgnoreCase("end")) out.println(header+"Programma terminato");
				else {
					//out.println(header+"Tu mi hai detto: "+msg);
					try {

						int k;
						for (k=0;k<users.size();k++) {
							Server user = (Server) users.elementAt(k);
							String outline = user.getFrom()+" "+user.getID()+": "+msg;
							System.out.println(k+") "+outline);
							user.getOutStrem().println(outline);
							user.getOutStrem().flush();
						}

					}
					catch(Exception e) {
						System.out.println("Impossibile inviare il messaggio a "+linkTosocket.getInetAddress());
						System.out.println(e);
					}

				}
				}
				catch(NullPointerException e) { System.out.println("ERROR: Connection from remote host has been closed"); }
				msg = null;
			}
			while(true); //!msg.equalsIgnoreCase("end")	
			
			
			// Chiudi gli stream
			//linkTosocket.close();
			//out.close();
			//in.close();
			//System.out.println("[+] Connection closed");
		}
		catch(IOException e) {
			System.out.println("IOException: "+ e);
		}
		System.out.println("[+] Connection closed");
		
	}
	
	public int getID() {
		return ID;
	}
	
	public String getFrom() {
		return from_name;
	}
	
	public PrintWriter getOutStrem() {
		return out;
	}
	
}
